package jazztures.helpers {

	import jazztures.Jazztures;
	import jazztures.events.CursorEvent;
	import jazztures.objects.Cursor;

	import flash.display.Stage;
	import flash.geom.Point;
	
	public class CursorHelper {
		private var _stage:Stage;
		private var _jazztures:Jazztures;
		
		private var _cursors:Array;
		
		private var _holdTimeout:Number = 5000;
		
		public function CursorHelper(stage:Stage, jazztures:Jazztures){
			_jazztures = jazztures;
			_stage = stage;
			
			_cursors = [];
			
			_jazztures.addEventListener(CursorEvent.UPDATE_CURSOR, cursorListener);
			_jazztures.addEventListener(CursorEvent.ADD_CURSOR, cursorListener);
			_jazztures.addEventListener(CursorEvent.REMOVE_CURSOR, cursorListener);
		}

		private function cursorListener(event : CursorEvent) : void {
			switch(event.type){
				case CursorEvent.ADD_CURSOR:
				case CursorEvent.UPDATE_CURSOR:
				var pointer:Pointer = _cursors[event.id] ? _cursors[event.id] : (_cursors[event.id] = new Pointer(event.id));
					pointer.position = new Point(event.x, event.y);
					pointer.delay = holdTimeout;
					pointer.objects = _stage.getObjectsUnderPoint(pointer.position);
				break;
				
				case CursorEvent.REMOVE_CURSOR:
				_cursors[event.id] = null;
				break;
			}
		}

		public function get holdTimeout() : Number {
			return _holdTimeout;
		}

		public function set holdTimeout(holdTimeout : Number) : void {
			_holdTimeout = holdTimeout;
		}
		
		public function get cursors():Vector.<Cursor>{
			var result:Vector.<Cursor> = new Vector.<Cursor>();
				for(var i:String in _cursors){
					var cursor:Cursor = new Cursor(_cursors[i].id);
					cursor.x = _cursors[i].x;
					cursor.y = _cursors[i].y;
					result.push(cursor);
				}
			return result;			
		}
	}
}

import jazztures.events.HoldEvent;

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.InteractiveObject;
import flash.geom.Point;
import flash.utils.Dictionary;
import flash.utils.getTimer;

internal class Pointer{
	private var _id:uint;
	private var timer:Number;
	private var currentObject:InteractiveObject;
	public var position:Point;
	public var delay:Number;
	
	public function Pointer(id:int){
		_id = id;
	}
	
	public function set objects(value:Array):void{
		var interactiveObject:InteractiveObject;
		var dict:Dictionary = new Dictionary(true);
		for(var i:int = 0; i<value.length; i++){
			var hierarchy:Array = getHierarchy(DisplayObject(value[i]));
			for(var j:int = hierarchy.length-1; j>=0; j--){
				if(!dict[hierarchy[j]]){
					interactiveObject = hierarchy[j];
					dict[hierarchy[j]] = true;
				}
			}
		}
		
		var currentTime:Number = getTimer() - timer;
		
		if(interactiveObject == null || interactiveObject!=currentObject){
			if(currentObject){
				currentObject.dispatchEvent(new HoldEvent(HoldEvent.HOLD_RELEASE, _id, position.x, position.y, currentTime));
			}
			currentObject = interactiveObject;
			if(interactiveObject){
				currentObject.dispatchEvent(new HoldEvent(HoldEvent.HOLD_START, _id, position.x, position.y, 0));
			}
			timer = getTimer();
			return;
		
		}else if(interactiveObject==currentObject){
			currentObject.dispatchEvent(new HoldEvent(HoldEvent.HOLD_PROGRESS, _id, position.x, position.y, Math.min(currentTime/delay, 1)));
			if(currentTime > delay){
				currentObject.dispatchEvent(new HoldEvent(HoldEvent.HOLD_COMPLETE, _id, position.x, position.y, 1));
				timer = getTimer();
			}
			
			return;
		}
	}
	
	private function getHierarchy(displayObject:DisplayObject):Array{
		var result:Array = [];
		while(displayObject.parent){
			if(displayObject is DisplayObjectContainer && !DisplayObjectContainer(displayObject).mouseChildren) result = [];
			if(displayObject is InteractiveObject && InteractiveObject(displayObject).mouseEnabled) result.push(displayObject);
			displayObject = displayObject.parent;	
		}
		return result;
	}
	
	public function get id():uint{
		return _id;
	}
	
	public function get x():Number{
		return position.x;
	}
	
	public function get y():Number{
		return position.y;
	}
}
